package org.mog.user.controller;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.json.JSONUtil;
import com.mog.api.feignClients.CommonClient;
import context.JwtContext;
import context.UserContext;
import context.WxContext;
import dto.UserInsertDTO;
import dto.UserUpdateDTO;
import entity.pojo.Url2FileMultipartFile;
import entity.pojo.User;
import entity.pojo.WxUser;
import entity.resullt.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.mog.user.properties.JwtProperties;
import org.mog.user.service.IUserService;
import org.mog.user.websocket.WebSocketServer;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import utils.AliOssUtils;
import utils.JwtUtil;
import utils.WxUtil;
import vo.UserLoginVO;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Api(tags = "用户相关接口")
@RestController
@RequiredArgsConstructor
@RequestMapping("/user/user")
@Slf4j
public class UserController {
    private final WxUtil wxUtil;
    private final IUserService userService;
    private final JwtProperties jwtProperties;
    private final AliOssUtils aliOssUtils;
    private final WebSocketServer webSocketServer;

    /**
     * 登录
     *
     * @param request
     * @param response
     * @return
     * @throws ServletException
     * @throws IOException
     */
    @PostMapping("/login")
    public Result<String> login(HttpServletRequest request,
                                HttpServletResponse response)
            throws ServletException, IOException {
        log.info("用户登录");
        return null;
    }

    /**
     * 微信登录显示二维码
     *
     * @param response
     * @param sid
     * @throws Exception
     */
    @GetMapping("/wxLogin/{sid}")
    public void wxLoginPage(HttpServletResponse response,
                            @PathVariable String sid) throws Exception {
        log.info("用户微信登录");
        //构造二维码链接地址
        String url = WxContext.spliceWxLoginQRCodeUrl(sid);
        //生成二维码，到响应的输出流
        response.setContentType("image/png");
        QrCodeUtil.generate(url, 300, 300, "jpg", response.getOutputStream());
    }

    /**
     * 微信登录二维码回调接口
     *
     * @param code
     * @param state
     * @param request
     * @param response
     * @param session
     * @param sid
     * @return
     * @throws IOException
     */
    @RequestMapping("wxCallback/{sid}")
    public String callBack(String code,
                           String state,
                           HttpServletRequest request,
                           HttpServletResponse response,
                           HttpSession session,
                           @PathVariable String sid) throws IOException {
        WxUser wxUser = wxUtil.getUserInfo(code);
        //昵称重新编码
        wxUser.setNickname(new String(wxUser.getNickname().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));

        //判断用户是否已经存在，若否保存用户信息
        User user = userService.getByOpenId(wxUser.getOpenid());
        String url;
        String nickName = "";
        Long id;
        if (user == null) {
            //用户不存在，添加用户
            //头像上传
            String fileUrl = wxUser.getHeadimgurl();
            int index = fileUrl.lastIndexOf(".");
            Url2FileMultipartFile multipartFile
                    = new Url2FileMultipartFile(
                    wxUser.getHeadimgurl(),
                    "file" + fileUrl.substring(index),
                    "file" + fileUrl.substring(index),
                    "image/jpeg"
            );

            //生成随机文件名
            String str = UUID.randomUUID().toString().replaceAll("-", "");
            String fileName = str + ".jpg";
            url = aliOssUtils.upload(multipartFile.getContent(), fileName);

            User newUser = userService.insert(
                    UserInsertDTO.builder()
                            .openId(wxUser.getOpenid())
                            .userId(Base64Encoder.encode(wxUser.getOpenid()))
                            .password("123456789")
                            .nickname(wxUser.getNickname())
                            .avatar(url)
                            .build()
            );
            id = newUser.getId();
        } else {
            id = user.getId();
            url = user.getAvatar();
            nickName = user.getNickname();
        }
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtContext.ID, id);

        String token = JwtUtil.createJWT(jwtProperties.getSecretKey(), jwtProperties.getTtl(), claims);
        log.info("token={}", token);

        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(id)
                .nickname(wxUser.getNickname())
                .token(token)
                .avatar(url)
                .build();
        if (StringUtils.isNotBlank(nickName)) {
            userLoginVO.setNickname(nickName);
        }

        //使用websocket向电脑前端发送已登录的消息
        webSocketServer.sent2Client(userLoginVO, sid);

        //加入ThreadLocal
        log.info("准备存放用户id：{}", id);
        UserContext.setId(id);

        request.setAttribute("res", userLoginVO.getNickname());
        return "<html><center><h1>登录成功！！！</h1></center></html>";

    }

    /**
     * 微信接入验证接口，用于验证是否接入成功
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @RequestMapping("/wxCheck")
    public String wxSignatureCheck(
            String signature,
            String timestamp,
            String nonce,
            String echostr
    ) {
        log.info("收到微信校验请求，echostr:{}", echostr);
        return echostr;
    }

    /**
     * 修改用户信息
     *
     * @param userUpdateDTO
     * @return
     */
    @PutMapping
    @ApiOperation("修改用户信息")
    public Result update(@RequestBody UserUpdateDTO userUpdateDTO) {
        log.info("修改用户信息：{}", userUpdateDTO);
        userService.update(userUpdateDTO);
        log.info("修改成功");
        return Result.success();
    }
}
